package com.fingerchar.api.service;

import com.fingerchar.core.constant.SysConfConstant;
import com.fingerchar.core.manager.FcSystemConfigManager;
import com.fingerchar.core.util.BigIntegerUtils;
import com.fingerchar.core.util.ResponseBean;
import com.fingerchar.core.util.ToolUtils;
import com.fingerchar.db.dao.ext.FcUserExtMapper;
import com.fingerchar.db.domain.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * nft交易
 *
 * @author tangzf
 * @date 2022/9/8
 */
@Service
public class NftTransService {

    @Resource
    private FcUserService fcUserService;
    @Resource
    private FcNftItemsService fcNftItemsService;
    @Resource
    private FcSystemConfigManager fcSystemConfigManager;
    @Resource
    private FcUserExtMapper fcUserExtMapper;
    @Resource
    private FcContractNftService fcContractNftService;
    @Resource
    private TtUsdtRechargeService ttUsdtRechargeService;
    @Resource
    private TtCalRecordService ttCalRecordService;
    @Resource
    private TtTntInRecordService ttTntInRecordService;
    @Resource
    private FcContractService fcContractService;
    @Resource
    private TtStatisticsAmountService ttStatisticsAmountService;
    @Resource
    private TtLevelService ttLevelService;


    public ResponseBean<?> check(String buyerAddress, String nftAddress, String nftTokenId) {

        FcUser buyerUser = fcUserService.getUserByAddress(buyerAddress);

        if (null == buyerUser) {
            return ResponseBean.error("用户不存在");
        }
        FcNftItems fcNftItems = fcNftItemsService.getByAddress(nftAddress, nftTokenId);
        if (null == fcNftItems || !fcNftItems.getOnsell()) {
            return ResponseBean.error("nft不存在或者不在销售中");
        }
        FcUser sellUser = fcUserService.getUserByAddress(fcNftItems.getItemOwner());
        BigInteger usdtAmount = buyerUser.getUsdtAmount();
        BigInteger price = new BigInteger(fcNftItems.getUsdtPrice());
        if (price.compareTo(usdtAmount) > 0) {
            return ResponseBean.error("udst余额不足");
        }
        String tntRate = fcSystemConfigManager.getKeyValue(SysConfConstant.TNT_AWARE_RATE);
        BigInteger tntAware = BigIntegerUtils.mulRate(price, tntRate);
        BigInteger tntAmount = sellUser.getTntAmount();
        if (tntAware.compareTo(tntAmount) > 0) {
            return ResponseBean.error("售卖者tnt余额不足");
        }
        //todo 校验某段时间内只能购买多少次

        return ResponseBean.success();
    }


    /**
     * 交易后台逻辑
     *
     * @param buyerAddress
     * @param nftAddress
     * @return
     */
    public ResponseBean<?> trans(String buyerAddress, String sellAddress, String nftAddress, String nftTokenId) {

        //查询并锁住行数据
        FcUser buyerUser = fcUserService.getLockUserByAddress(buyerAddress);
        if (null == buyerUser) {
            return ResponseBean.error("用户不存在");
        }
        FcNftItems fcNftItems = fcNftItemsService.getByAddress(nftAddress, nftTokenId);
        if (null == fcNftItems || !fcNftItems.getOnsell()) {
            return ResponseBean.error("nft不存在或者不在销售中");
        }


        //买方：扣除对应nft价格的usdt;
        BigInteger price = new BigInteger(fcNftItems.getPrice());
        int row = fcUserService.reduceUsdtAmount(buyerAddress, price);
        //买方：生成usdt 扣减记录
        BigInteger reduceUsdtAmount = new BigInteger("-" + fcNftItems.getPrice());
        TtUsdtRecharge usdtRecharge = TtUsdtRecharge.builder()
                .userAddress(buyerAddress)
                .createTime(System.currentTimeMillis())
                .amount(reduceUsdtAmount)
                .optType("3")
                .hash("")//todo
                .build();
        int row2 = ttUsdtRechargeService.insert(usdtRecharge);
        //买方: 第一次购买赠送100算力
        if ("0".equals(buyerUser.getFirstBuy())) {
            BigInteger amount = new BigInteger("100");
            fcUserService.addCalAmount(buyerAddress, amount);
            TtCalRecord ttCalRecord = TtCalRecord.builder()
                    .userAddress(buyerAddress)
                    .inCalType("0")
                    .amount(amount)
                    .build();
            ttCalRecordService.insert(ttCalRecord);
        }
        //买方：获取nft价值的算力
        BigInteger calAmount = new BigInteger(fcNftItems.getPrice());
        fcUserService.addCalAmount(buyerAddress, calAmount);
        TtCalRecord ttCalRecord = TtCalRecord.builder()
                .userAddress(buyerAddress)
                .inCalType("1")
                .amount(calAmount)
                .build();
        ttCalRecordService.insert(ttCalRecord);

        //卖方：扣除8%的tnt
        String tntRate = fcSystemConfigManager.getKeyValue(SysConfConstant.TNT_AWARE_RATE);
        BigInteger tntAware = BigIntegerUtils.mulRate(price, tntRate);
        int row4 = fcUserService.reduceTntAmount(sellAddress, tntAware);
        if (1 != row4) {
            throw new RuntimeException("扣除卖方的tnt失败");
        }
        BigInteger tntAware2 = BigIntegerUtils.mulRate(price, tntRate).multiply(new BigInteger("-1"));
        TtTntInRecord tntInRecord = TtTntInRecord.builder()
                .inType("2")
                .tntAmount(tntAware2)
                .orderId(0L)
                .userAddress(sellAddress)
                .build();
        //增加个人扣除tnt记录
        ttTntInRecordService.addRecord(tntInRecord);

        //卖方: 增加98%的usdt收益；
        BigInteger usdtSellAmount = BigIntegerUtils.mulRate(price, "98");
        fcUserService.addUsdtAmount(sellAddress, usdtSellAmount);
        ttUsdtRechargeService.insert("", sellAddress, usdtSellAmount, "2");

        //平台方：增加1%的usdt收益；
        String platformAddress = fcSystemConfigManager.getKeyValue(SysConfConstant.TNT_USER_ADDRESS);
        BigInteger usdtPlatformAmount = BigIntegerUtils.mulRate(price, "1");
        fcUserService.addUsdtAmount(platformAddress, usdtPlatformAmount);
        ttUsdtRechargeService.insert("", platformAddress, usdtPlatformAmount, "2");

        //铸造者：增加1%的usdt收益；
        String ownerAddress = fcContractNftService.getDetail(fcNftItems.getAddress(), fcNftItems.getTokenId()).getCreator();
        BigInteger usdtOwnerAmount = BigIntegerUtils.mulRate(price, "1");
        fcUserService.addUsdtAmount(ownerAddress, usdtOwnerAmount);
        ttUsdtRechargeService.insert("", ownerAddress, usdtOwnerAmount, "2");


        //增加 购买者业绩
        ttStatisticsAmountService.addPersonalAmount(buyerAddress, price);

        Long parentId = buyerUser.getParentId();

        while (null != parentId) {
            //增加购买者上级的团队业绩
            FcUser parentUser = fcUserService.findById(parentId);
            ttStatisticsAmountService.addTeamAmount(parentUser.getAddress(), price);
            parentId = parentUser.getParentId();
        }

        //直推奖励处理


        //级差奖励
        List<TtLevel> ttLevelList = ttLevelService.getAll();
        Map<String, TtLevel> levelMap = ttLevelList.stream().collect(Collectors.toMap(TtLevel::getLevelNo, l -> l));
        Long levelParentId = buyerUser.getParentId();
        TtLevel level = levelMap.get(buyerUser.getLevelNo());
        //级差奖励
        BigInteger levelAmount = price;
        while (null != levelParentId || levelAmount.compareTo(BigInteger.ZERO) <= 0) {

            FcUser parentUser = fcUserService.findById(levelParentId);

            //增加购买者所有上级的级差奖励(算力奖励)
            TtLevel parentLevel = levelMap.get(parentUser.getLevelNo());
            int equalReward = parentLevel.getDirectReward() - level.getDirectReward();
            if (equalReward > 0) {
                levelAmount = BigIntegerUtils.mulRate(levelAmount, Integer.toString(equalReward));
                fcUserService.addCalAmount(parentUser.getAddress(), levelAmount);
                TtCalRecord ttCalRecord2 = TtCalRecord.builder()
                        .userAddress(parentUser.getAddress())
                        .inCalType("5")
                        .amount(levelAmount)
                        .build();
                ttCalRecordService.insert(ttCalRecord2);
            } else {
                //跳出循环
                levelAmount = BigInteger.ZERO;
            }
            levelParentId = parentUser.getParentId();
        }


        //级差奖励

        //平级奖励


        //

        return null;
    }

}
